// Package service @author dingrui @since 2021/11/27
package service

import (
	"fmt"
	"log"
	"sync"

	"github.com/gomodule/redigo/redis"

	"github.com/bannirui/mini-prize/common"
	"github.com/bannirui/mini-prize/dal/dao"
	"github.com/bannirui/mini-prize/dal/model"
	"github.com/bannirui/mini-prize/datasource"
)

var (
	G_userService  UserService
	cachedUserList = make(map[int]*model.User)
	cachedUserLock = sync.Mutex{}
)

type UserService interface {
	GetAll(page, size int) []model.User
	CountAll() int
	Get(id int) *model.User
	Update(user *model.User, columns []string) error
	Create(user *model.User) error
}

type userService struct {
	dao *dao.UserDao
}

func init() {
	G_userService = &userService{
		dao: dao.G_userDao,
	}
}

func (s *userService) GetAll(page, size int) []model.User {
	return s.dao.PageAll(page, size)
}

func (s *userService) CountAll() int {
	return s.dao.CountAll()
}

func (s *userService) Get(id int) *model.User {
	data := s.getByCache(id)
	if data == nil || data.Id <= 0 {
		data = s.dao.GetById(id)
		if data == nil || data.Id <= 0 {
			data = &model.User{Id: id}
		}
		s.setByCache(data)
	}
	return data
}

func (s *userService) Update(data *model.User, columns []string) error {
	// 先更新缓存
	s.updateByCache(data, columns)
	// 然后再更新数据
	return s.dao.Update(data, columns)
}

func (s *userService) Create(data *model.User) error {
	return s.dao.InsertOne(data)
}

// 从缓存中得到信息
func (s *userService) getByCache(id int) *model.User {
	// 集群模式，redis缓存
	key := fmt.Sprintf("info_user_%d", id)
	dataMap, err := redis.StringMap(datasource.G_redis.Do("HGETALL", key))
	if err != nil {
		log.Println("user_service.getByCache HGETALL key=", key, ", error=", err)
		return nil
	}
	dataId := common.GetInt64FromStringMap(dataMap, "Id", 0)
	if dataId <= 0 {
		return nil
	}
	data := &model.User{
		Id:              int(dataId),
		Username:        common.GetStringFromStringMap(dataMap, "Username", ""),
		BlackExpireTime: int(common.GetInt64FromStringMap(dataMap, "BlackExpireTime", 0)),
		RealName:        common.GetStringFromStringMap(dataMap, "RealName", ""),
		Phone:           common.GetStringFromStringMap(dataMap, "Phone", ""),
		Address:         common.GetStringFromStringMap(dataMap, "Address", ""),
		GmtCreated:      int(common.GetInt64FromStringMap(dataMap, "GmtCreated", 0)),
		GmtUpdated:      int(common.GetInt64FromStringMap(dataMap, "GmtUpdated", 0)),
		Ip:              common.GetStringFromStringMap(dataMap, "Ip", ""),
	}
	return data
}

// 将信息更新到缓存
func (s *userService) setByCache(data *model.User) {
	if data == nil || data.Id <= 0 {
		return
	}
	id := data.Id
	// 集群模式，redis缓存
	key := fmt.Sprintf("info_user_%d", id)
	// 数据更新到redis缓存
	params := []interface{}{key}
	params = append(params, "Id", id)
	if data.Username != "" {
		params = append(params, "Username", data.Username)
		params = append(params, "BlackExpireTime", data.BlackExpireTime)
		params = append(params, "RealName", data.RealName)
		params = append(params, "Phone", data.Phone)
		params = append(params, "Address", data.Address)
		params = append(params, "GmtCreated", data.GmtCreated)
		params = append(params, "GmtUpdated", data.GmtUpdated)
		params = append(params, "Ip", data.Ip)
	}
	_, err := datasource.G_redis.Do("HMSET", params...)
	if err != nil {
		log.Println("user_service.setByCache HMSET params=", params, ", error=", err)
	}
}

// 数据更新了，直接清空缓存数据
func (s *userService) updateByCache(data *model.User, columns []string) {
	if data == nil || data.Id <= 0 {
		return
	}
	// 集群模式，redis缓存
	key := fmt.Sprintf("info_user_%d", data.Id)
	// 删除redis中的缓存
	_, _ = datasource.G_redis.Do("DEL", key)
}
